//unity before version 5 is old
//#define USE_OLD_UNITY 

using UnityEngine;
//using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;


[System.Serializable]
public class Images
{
	public Texture2D   	clearImage;
	public Texture2D   	collapseImage;
	public Texture2D   	clearOnNewSceneImage;
	public Texture2D   	showTimeImage;
	public Texture2D   	showSceneImage;
	public Texture2D   	userImage;
	public Texture2D   	showMemoryImage;
	public Texture2D   	softwareImage;
	public Texture2D   	dateImage;
	public Texture2D   	showFpsImage;
	public Texture2D   	showGraphImage;
	public Texture2D   	graphImage;
	public Texture2D   	infoImage;
	public Texture2D    searchImage;
	public Texture2D   	closeImage;
	
	public Texture2D   	buildFromImage;
	public Texture2D   	systemInfoImage;
	public Texture2D   	graphicsInfoImage;
	public Texture2D   	backImage;
	public Texture2D   	cameraImage;
	
	public Texture2D   	logImage;
	public Texture2D   	warningImage;
	public Texture2D   	errorImage;

	public Texture2D 	barImage;
	public Texture2D	button_activeImage;
	public Texture2D	even_logImage;
	public Texture2D 	odd_logImage;
	public Texture2D	selectedImage;

	public GUISkin		reporterScrollerSkin;
}
//just drop this script to empty game object on first scene you game start at, this all what you have to do
//no coding is required 
//then you can view logs , warnings , errors and exceptions inside your game
//just draw circle on your game to view all logs
public class Reporter : MonoBehaviour {


	public enum _LogType{
		Assert 	= LogType.Assert ,
		Error  	= LogType.Error ,
		Exception = LogType.Exception ,
		Log 	= LogType.Log ,
		Warning = LogType.Warning ,
	}
	public class Sample
	{
		public float 	time ;
		public byte 	loadedScene ;
		public float 	memory ;
		public float 	fps ;
		public string  	fpsText ;
		public static float MemSize(){
			float s = sizeof( float ) + sizeof( byte ) + sizeof( float ) + sizeof( float ) ;
			return  s;
		}
	}

	List<Sample>	samples = new List<Sample>( 60 * 60 * 60 );

	public class Log
	{
		public int 	   		count = 1;	
		public _LogType 	logType ;
		public string  		condition ;
		public string  		stacktrace ;
		public int 			sampleId ;
		//public string   objectName="" ;//object who send error
		//public string   rootName =""; //root of object send error

		public Log CreateCopy()
		{
			return (Log)this.MemberwiseClone();
		}
		public float GetMemoryUsage()
		{
			return 	(float)(sizeof(int) + 
			        sizeof(_LogType) +
			        condition.Length * sizeof( char )+
			        stacktrace.Length * sizeof( char )+
					sizeof( int ) );
		}
	}
	//contains all uncollapsed log
	List<Log> logs = new List<Log>();
	//contains all collapsed logs
	List<Log> collapsedLogs = new List<Log>();
	//contain logs which should only appear to user , for example if you switch off show logs + switch off show warnings
	//and your mode is collapse,then this list will contains only collapsed errors
	List<Log> currentLog = new List<Log>();
	
	//used to check if the new coming logs is already exist or new one
	MultiKeyDictionary<string,string, Log> logsDic = new MultiKeyDictionary<string, string, Log>();
	//to save memory
	Dictionary<string , string > cachedString = new Dictionary<string, string>();

	[HideInInspector]
	//show hide In Game Logs
	public bool show = false ;
	//collapse logs
	bool collapse ;
	//to deside if you want to clean logs for new loaded scene
	bool clearOnNewSceneLoaded ;

	bool showTime ;

	bool showScene ;

	bool showMemory ;

	bool showFps ;

	bool showGraph ;

	//show or hide logs
	bool showLog = true ;
	//show or hide warnings
	bool showWarning = true ;
	//show or hide errors
	bool showError = true ;
	
	//total number of logs
	int numOfLogs=0;
	//total number of warnings
	int numOfLogsWarning=0;
	//total number of errors
	int numOfLogsError=0;
	//total number of collapsed logs
	int numOfCollapsedLogs=0 ;
	//total number of collapsed warnings
	int numOfCollapsedLogsWarning =0;
	//total number of collapsed errors
	int numOfCollapsedLogsError =0;
	
	//maximum number of allowed logs to view
	//public int maxAllowedLog = 1000 ;

	bool showClearOnNewSceneLoadedButton = true ;
	bool showTimeButton = true;
	bool showSceneButton = true;
	bool showMemButton = true;
	bool showFpsButton = true;
	bool showSearchText = true;
	
	string buildDate;
	string logDate ;
	float  logsMemUsage;
	float  graphMemUsage ;
	public float TotalMemUsage{
		get{
			return logsMemUsage + graphMemUsage ;
		}
	}
	float  gcTotalMemory ;
	public string UserData = "";
	//fram rate per seconds
	public float fps ;
	public string fpsText ;

	//List<Texture2D> snapshots = new List<Texture2D>() ;

	enum ReportView
	{
		None ,
		Logs ,
		Info ,
		Snapshot ,
	}
	ReportView currentView = ReportView.Logs ;
	enum DetailView
	{
		None ,
		StackTrace ,
		Graph ,
	}

	//used to check if you have In Game Logs multiple time in different scene
	//only one should work and other should be deleted
	static bool created = false ;
	//public delegate void OnLogHandler( string condition, string stacktrace, LogType type );
	//public event OnLogHandler OnLog ;

	public Images images;
	// gui
	GUIContent 	clearContent ;
	GUIContent 	collapseContent ;
	GUIContent 	clearOnNewSceneContent ;
	GUIContent 	showTimeContent ;
	GUIContent 	showSceneContent ;
	GUIContent 	userContent ;
	GUIContent 	showMemoryContent ;
	GUIContent 	softwareContent ;
	GUIContent 	dateContent ;
	GUIContent 	showFpsContent ;
	GUIContent 	graphContent ;
	GUIContent 	infoContent ;
	GUIContent 	searchContent ;
	GUIContent 	closeContent ;


	GUIContent 	buildFromContent ;
	GUIContent  systemInfoContent ;
	GUIContent  graphicsInfoContent ;
	GUIContent 	backContent ;

	GUIContent 	cameraContent ;
	

	GUIContent 	logContent ;
	GUIContent 	warningContent ;
	GUIContent 	errorContent ;
	GUIStyle   	barStyle ;
	GUIStyle   	buttonActiveStyle ;

	GUIStyle   	nonStyle ;
	GUIStyle   	lowerLeftFontStyle ;
	GUIStyle   	backStyle ;
	GUIStyle   	evenLogStyle ;
	GUIStyle   	oddLogStyle ;
	GUIStyle   	logButtonStyle ;
	GUIStyle   	selectedLogStyle ;
	GUIStyle   	selectedLogFontStyle ;
	GUIStyle   	stackLabelStyle ;
	GUIStyle   	scrollerStyle ;
	GUIStyle   	searchStyle ;
	GUIStyle   	sliderBackStyle ;
	GUIStyle   	sliderThumbStyle ;
	GUISkin 	toolbarScrollerSkin ;
	GUISkin 	logScrollerSkin ;
	GUISkin 	graphScrollerSkin ;
	
	public Vector2 size = new Vector2( 32 , 32 ) ;
	public float maxSize = 20 ;
	public int numOfCircleToShow = 1 ;
	string[] scenes ;
	string   currentScene ;
	string   filterText="";

	string deviceModel ;
	string deviceType ;
	string deviceName ;
	string graphicsMemorySize ;
	#if !USE_OLD_UNITY
	string maxTextureSize ;
	#endif
	string systemMemorySize ;

	void Awake()
	{
		if( !Initialized )
			Initialize();
	}
	
	void OnEnable()
	{
		if( logs.Count == 0 )//if recompile while in play mode
			clear(); 
	}
	void OnDisable()
	{ 
		
	}

	void addSample(){

		Sample sample = new Sample();
		sample.fps = fps ;
		sample.fpsText = fpsText ;
		sample.loadedScene = 0 ;
		sample.time = Time.realtimeSinceStartup ;
		sample.memory = gcTotalMemory ;
		samples.Add( sample );

		graphMemUsage = (samples.Count * Sample.MemSize())/1024/1024;
	}

	public bool Initialized = false ;
	public void Initialize()
	{
		if( !created )
		{
			try{
				gameObject.SendMessage( "OnPreStart" );
			}
			catch( System.Exception e ){
				Debug.LogException( e );
			}
			scenes = new string[SceneManager.sceneCountInBuildSettings];
			currentScene = Application.loadedLevelName;
			DontDestroyOnLoad( gameObject );
#if USE_OLD_UNITY
			Application.RegisterLogCallback (new Application.LogCallback (CaptureLog));
			Application.RegisterLogCallbackThreaded (new Application.LogCallback (CaptureLogThread));
#else
			//Application.logMessageReceived += CaptureLog ;
			Application.logMessageReceivedThreaded += CaptureLogThread ;
#endif
			created = true ;
			//addSample();
		}
		else 
		{
			Debug.LogWarning("tow manager is exists delete the second");
			DestroyImmediate( gameObject ,true);
			return;
		}


		//initialize gui and styles for gui porpose

		clearContent 	= new GUIContent("",images.clearImage,"Clear logs");
		collapseContent = new GUIContent("",images.collapseImage,"Collapse logs");
		clearOnNewSceneContent = new GUIContent("",images.clearOnNewSceneImage,"Clear logs on new scene loaded");
		showTimeContent = new GUIContent("",images.showTimeImage,"Show Hide Time");
		showSceneContent = new GUIContent("",images.showSceneImage,"Show Hide Scene");
		showMemoryContent = new GUIContent("",images.showMemoryImage,"Show Hide Memory");
		softwareContent = new GUIContent("",images.softwareImage,"Software");
		dateContent = new GUIContent("",images.dateImage,"Date");
		showFpsContent = new GUIContent("",images.showFpsImage,"Show Hide fps");
		graphContent = new GUIContent("",images.showGraphImage,"Show Graph");
		infoContent = new GUIContent("",images.infoImage,"Information about application");
		searchContent = new GUIContent("",images.searchImage,"Search for logs");
		closeContent = new GUIContent("",images.closeImage,"Hide logs");
		userContent = new GUIContent("",images.userImage,"User");

		buildFromContent = new GUIContent("",images.buildFromImage,"Build From");
		systemInfoContent = new GUIContent("",images.systemInfoImage,"System Info");
		graphicsInfoContent = new GUIContent("",images.graphicsInfoImage,"Graphics Info");
		backContent = new GUIContent("",images.backImage,"Back");

		cameraContent = new GUIContent("",images.cameraImage,"Select Photo");



		//snapshotContent = new GUIContent("",images.cameraImage,"show or hide logs");
		logContent 	= new GUIContent("",images.logImage,"show or hide logs");
		warningContent = new GUIContent("",images.warningImage,"show or hide warnings");
		errorContent = new GUIContent("",images.errorImage,"show or hide errors");


		currentView = (ReportView)PlayerPrefs.GetInt( "Reporter_currentView" , 1);
		show 		= (PlayerPrefs.GetInt( "Reporter_show" )==1)?true:false;
		collapse 	= (PlayerPrefs.GetInt( "Reporter_collapse" )==1)?true:false;
		clearOnNewSceneLoaded = (PlayerPrefs.GetInt( "Reporter_clearOnNewSceneLoaded" )==1)?true:false;
		showTime 	= (PlayerPrefs.GetInt( "Reporter_showTime" )==1)?true:false;
		showScene 	= (PlayerPrefs.GetInt( "Reporter_showScene" )==1)?true:false;
		showMemory 	= (PlayerPrefs.GetInt( "Reporter_showMemory" )==1)?true:false;
		showFps 	= (PlayerPrefs.GetInt( "Reporter_showFps" )==1)?true:false;
		showGraph 	= (PlayerPrefs.GetInt( "Reporter_showGraph" )==1)?true:false;
		showLog 	= (PlayerPrefs.GetInt( "Reporter_showLog" ,1) ==1)?true:false;
		showWarning = (PlayerPrefs.GetInt( "Reporter_showWarning" ,1) ==1)?true:false;
		showError 	= (PlayerPrefs.GetInt( "Reporter_showError" ,1) ==1)?true:false;
		filterText  = PlayerPrefs.GetString("Reporter_filterText");
		size.x = size.y = PlayerPrefs.GetFloat( "Reporter_size" , 32 );


		showClearOnNewSceneLoadedButton 		= (PlayerPrefs.GetInt( "Reporter_showClearOnNewSceneLoadedButton" ,1)==1)?true:false;
		showTimeButton 		= (PlayerPrefs.GetInt( "Reporter_showTimeButton",1 )==1)?true:false;
		showSceneButton 	= (PlayerPrefs.GetInt( "Reporter_showSceneButton",1 )==1)?true:false;
		showMemButton 		= (PlayerPrefs.GetInt( "Reporter_showMemButton",1 )==1)?true:false;
		showFpsButton 		= (PlayerPrefs.GetInt( "Reporter_showFpsButton",1 )==1)?true:false;
		showSearchText 		= (PlayerPrefs.GetInt( "Reporter_showSearchText",1 )==1)?true:false;


		initializeStyle();

		Initialized = true ;

        if (show && (Application.targetFrameRate == 46 || Application.loadedLevelName != "Battle"))
        {          
			doShow();
		}

		deviceModel = SystemInfo.deviceModel.ToString() ;
		deviceType  = SystemInfo.deviceType.ToString() ;
		deviceName  = SystemInfo.deviceName.ToString() ;
		graphicsMemorySize = SystemInfo.graphicsMemorySize.ToString() ;
		#if !USE_OLD_UNITY
		maxTextureSize = SystemInfo.maxTextureSize.ToString() ;
		#endif
		systemMemorySize = SystemInfo.systemMemorySize.ToString() ; 

	}

	void initializeStyle()
	{
		int paddingX = (int)(size.x*0.2f) ;
		int paddingY = (int)(size.y*0.2f) ;
		nonStyle = new GUIStyle();
		nonStyle.clipping = TextClipping.Clip;
		nonStyle.border = new RectOffset(0,0,0,0);
		nonStyle.normal.background = null ;
		nonStyle.fontSize = (int)(size.y /2 );
		nonStyle.alignment = TextAnchor.MiddleCenter ;
		
		lowerLeftFontStyle = new GUIStyle();
		lowerLeftFontStyle.clipping = TextClipping.Clip;
		lowerLeftFontStyle.border = new RectOffset(0,0,0,0);
		lowerLeftFontStyle.normal.background = null ;
		lowerLeftFontStyle.fontSize = (int)(size.y /2 );
		lowerLeftFontStyle.fontStyle = FontStyle.Bold ;
		lowerLeftFontStyle.alignment = TextAnchor.LowerLeft ;
		
		
		barStyle = new GUIStyle();
		barStyle.border = new RectOffset(1,1,1,1);
		barStyle.normal.background = images.barImage ;
		barStyle.active.background = images.button_activeImage ;
		barStyle.alignment = TextAnchor.MiddleCenter ;
		barStyle.margin = new RectOffset(1,1,1,1);
		
		//barStyle.padding = new RectOffset(paddingX,paddingX,paddingY,paddingY); 
		//barStyle.wordWrap = true ;
		barStyle.clipping = TextClipping.Clip;
		barStyle.fontSize = (int)(size.y /2 );
		
		
		buttonActiveStyle = new GUIStyle();
		buttonActiveStyle.border = new RectOffset(1,1,1,1);
		buttonActiveStyle.normal.background = images.button_activeImage;
		buttonActiveStyle.alignment = TextAnchor.MiddleCenter ;
		buttonActiveStyle.margin = new RectOffset(1,1,1,1);
		//buttonActiveStyle.padding = new RectOffset(4,4,4,4);
		buttonActiveStyle.fontSize = (int)(size.y /2 );
		
		backStyle = new GUIStyle();
		backStyle.normal.background = images.even_logImage;
		backStyle.clipping = TextClipping.Clip ;
		backStyle.fontSize = (int)(size.y /2 );
		
		evenLogStyle = new GUIStyle();
		evenLogStyle.normal.background = images.even_logImage;
		evenLogStyle.fixedHeight = size.y ;
		evenLogStyle.clipping = TextClipping.Clip ;
		evenLogStyle.alignment = TextAnchor.UpperLeft ;
		evenLogStyle.imagePosition = ImagePosition.ImageLeft ;
		evenLogStyle.fontSize = (int)(size.y /2 );
		//evenLogStyle.wordWrap = true;
		
		oddLogStyle = new GUIStyle();
		oddLogStyle.normal.background = images.odd_logImage;
		oddLogStyle.fixedHeight = size.y ;
		oddLogStyle.clipping = TextClipping.Clip ;
		oddLogStyle.alignment = TextAnchor.UpperLeft ;
		oddLogStyle.imagePosition = ImagePosition.ImageLeft ;
		oddLogStyle.fontSize = (int)(size.y /2 );
		//oddLogStyle.wordWrap = true ;
		
		logButtonStyle = new GUIStyle();
		//logButtonStyle.wordWrap = true;
		logButtonStyle.fixedHeight = size.y ;
		logButtonStyle.clipping = TextClipping.Clip ;
		logButtonStyle.alignment = TextAnchor.UpperLeft ;
		//logButtonStyle.imagePosition = ImagePosition.ImageLeft ;
		//logButtonStyle.wordWrap = true;
		logButtonStyle.fontSize = (int)(size.y /2 );
		logButtonStyle.padding = new RectOffset(paddingX,paddingX,paddingY,paddingY); 
		
		selectedLogStyle = new GUIStyle();
		selectedLogStyle.normal.background = images.selectedImage;
		selectedLogStyle.fixedHeight = size.y ;
		selectedLogStyle.clipping = TextClipping.Clip ;
		selectedLogStyle.alignment = TextAnchor.UpperLeft ;
		selectedLogStyle.normal.textColor = Color.white ;
		//selectedLogStyle.wordWrap = true;
		selectedLogStyle.fontSize = (int)(size.y /2 );
		
		selectedLogFontStyle = new GUIStyle();
		selectedLogFontStyle.normal.background = images.selectedImage;
		selectedLogFontStyle.fixedHeight = size.y ;
		selectedLogFontStyle.clipping = TextClipping.Clip ;
		selectedLogFontStyle.alignment = TextAnchor.UpperLeft ;
		selectedLogFontStyle.normal.textColor = Color.white ;
		//selectedLogStyle.wordWrap = true;
		selectedLogFontStyle.fontSize = (int)(size.y /2 );
		selectedLogFontStyle.padding = new RectOffset(paddingX,paddingX,paddingY,paddingY); 
		
		stackLabelStyle = new GUIStyle();
		stackLabelStyle.wordWrap = true ;
		stackLabelStyle.fontSize = (int)(size.y /2 );
		stackLabelStyle.padding = new RectOffset(paddingX,paddingX,paddingY,paddingY); 
		
		scrollerStyle = new GUIStyle(); 
		scrollerStyle.normal.background =  images.barImage;
		
		searchStyle = new GUIStyle();
		searchStyle.clipping = TextClipping.Clip ;
		searchStyle.alignment = TextAnchor.LowerCenter ;
		searchStyle.fontSize = (int)(size.y /2 );
		searchStyle.wordWrap = true;


		sliderBackStyle = new GUIStyle();
		sliderBackStyle.normal.background =  images.barImage;
		sliderBackStyle.fixedHeight = size.y;
		sliderBackStyle.border = new RectOffset(1,1,1,1);

		sliderThumbStyle = new GUIStyle();
		sliderThumbStyle.normal.background = images.selectedImage;
		sliderThumbStyle.fixedWidth = size.x ;

		GUISkin skin = images.reporterScrollerSkin ;
		
		toolbarScrollerSkin = (GUISkin)GameObject.Instantiate( skin );
		toolbarScrollerSkin.verticalScrollbar.fixedWidth = 0f ;
		toolbarScrollerSkin.horizontalScrollbar.fixedHeight = 0f ;
		toolbarScrollerSkin.verticalScrollbarThumb.fixedWidth = 0f;
		toolbarScrollerSkin.horizontalScrollbarThumb.fixedHeight = 0f;
		
		logScrollerSkin = (GUISkin)GameObject.Instantiate( skin );
		logScrollerSkin.verticalScrollbar.fixedWidth = size.x * 2f ;
		logScrollerSkin.horizontalScrollbar.fixedHeight = 0f ;
		logScrollerSkin.verticalScrollbarThumb.fixedWidth = size.x * 2f;
		logScrollerSkin.horizontalScrollbarThumb.fixedHeight = 0f;
		
		graphScrollerSkin = (GUISkin)GameObject.Instantiate( skin );
		graphScrollerSkin.verticalScrollbar.fixedWidth = 0f ;
		graphScrollerSkin.horizontalScrollbar.fixedHeight = size.x * 2f ;
		graphScrollerSkin.verticalScrollbarThumb.fixedWidth = 0f;
		graphScrollerSkin.horizontalScrollbarThumb.fixedHeight = size.x * 2f;
		//inGameLogsScrollerSkin.verticalScrollbarThumb.fixedWidth = size.x * 2;
		//inGameLogsScrollerSkin.verticalScrollbar.fixedWidth = size.x * 2;
	}

	void Start () {
		logDate = System.DateTime.Now.ToString() ;
		StartCoroutine("readInfo");
		
	}
	
	//clear all logs
	void clear()
	{
		logs.Clear();
		collapsedLogs.Clear();
		currentLog.Clear();
		logsDic.Clear();
		//selectedIndex = -1;
		selectedLog = null;
		numOfLogs = 0;
		numOfLogsWarning = 0;
		numOfLogsError = 0;
		numOfCollapsedLogs = 0;
		numOfCollapsedLogsWarning = 0;
		numOfCollapsedLogsError = 0;
		logsMemUsage = 0 ;
		graphMemUsage = 0;
		samples.Clear();
		System.GC.Collect();
		selectedLog = null;
	}

	Rect	screenRect  ;
	Rect	toolBarRect  ;
	Rect	logsRect  ;
	Rect 	stackRect  ;
	Rect    graphRect ;
	Rect    graphMinRect ;
	Rect    graphMaxRect ;
	Rect 	buttomRect  ;
	Vector2 stackRectTopLeft ;
	Rect 	detailRect  ;

	Vector2 scrollPosition;
	Vector2 scrollPosition2;
	Vector2 toolbarScrollPosition;

	//int 	selectedIndex = -1;
	Log     selectedLog ;

	float 	toolbarOldDrag =0;
	float 	oldDrag ;
	float 	oldDrag2 ;
	float 	oldDrag3 ;
	int 	startIndex;
	
	//calculate what is the currentLog : collapsed or not , hide or view warnings ......
	void calculateCurrentLog()
	{
		bool filter = !string.IsNullOrEmpty( filterText );
		string _filterText = "";
		if( filter )
			_filterText = filterText.ToLower();
		currentLog.Clear();
		if( collapse )
		{
			for( int i = 0 ; i < collapsedLogs.Count ; i++ )
			{
				Log log = collapsedLogs[i];
				if( log.logType == _LogType.Log && !showLog )
					continue;
				if( log.logType == _LogType.Warning && !showWarning )
					continue;
				if( log.logType == _LogType.Error && !showError )
					continue;
				if( log.logType == _LogType.Assert && !showError )
					continue;
				if( log.logType == _LogType.Exception && !showError )
					continue;

				if( filter )
				{
					if( log.condition.ToLower().Contains(_filterText))
						currentLog.Add( log );
				}
				else 
				{
					currentLog.Add( log );
				}
			}
		}
		else 
		{
			for( int i = 0 ; i < logs.Count ; i++ )
			{
				Log log = logs[i];
				if( log.logType == _LogType.Log && !showLog )
					continue;
				if( log.logType == _LogType.Warning && !showWarning )
					continue;
				if( log.logType == _LogType.Error && !showError )
					continue;
				if( log.logType == _LogType.Assert && !showError )
					continue;
				if( log.logType == _LogType.Exception && !showError )
					continue;

				if( filter )
				{
					if( log.condition.ToLower().Contains(_filterText))
						currentLog.Add( log );
				}
				else 
				{
					currentLog.Add( log );
				}
			}
		}

		if( selectedLog != null )
		{
			int newSelectedIndex = currentLog.IndexOf( selectedLog );
			if( newSelectedIndex == -1 )
			{
				Log collapsedSelected = logsDic[selectedLog.condition][selectedLog.stacktrace];
				newSelectedIndex = currentLog.IndexOf( collapsedSelected );
				if( newSelectedIndex != -1)
					scrollPosition.y = newSelectedIndex * size.y ;
			}
			else 
			{
				scrollPosition.y = newSelectedIndex * size.y ;
			}
		}
	}
	
	Rect countRect ;
	Rect timeRect ;
	Rect timeLabelRect ;
	Rect sceneRect ;
	Rect sceneLabelRect ;
	Rect memoryRect ;
	Rect memoryLabelRect ;
	Rect fpsRect ;
	Rect fpsLabelRect ;
	GUIContent tempContent = new GUIContent();

	Vector2 infoScrollPosition ;
	Vector2 oldInfoDrag ;
	void DrawInfo()
	{

		GUILayout.BeginArea( screenRect , backStyle );

		Vector2 drag = getDrag(); 
		if( (drag.x != 0) && (downPos != Vector2.zero)  )
		{
			infoScrollPosition.x -= (drag.x - oldInfoDrag.x) ;
		}
		if( (drag.y != 0) && (downPos != Vector2.zero)  )
		{
			infoScrollPosition.y += (drag.y - oldInfoDrag.y) ;
		}
		oldInfoDrag = drag;

		GUI.skin = toolbarScrollerSkin ;
		infoScrollPosition = GUILayout.BeginScrollView( infoScrollPosition ) ;
		GUILayout.Space( size.x);
		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( buildFromContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( buildDate , nonStyle, GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( systemInfoContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( deviceModel , nonStyle , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( deviceType , nonStyle , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( deviceName , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( graphicsInfoContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( SystemInfo.graphicsDeviceName , nonStyle , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( graphicsMemorySize , nonStyle , GUILayout.Height(size.y));
		#if !USE_OLD_UNITY
		GUILayout.Space( size.x);
		GUILayout.Label( maxTextureSize , nonStyle , GUILayout.Height(size.y));
		#endif
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Space( size.x);
		GUILayout.Space( size.x);
		GUILayout.Label( "Screen Width " + Screen.width, nonStyle , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label(  "Screen Height " + Screen.height ,nonStyle , GUILayout.Height(size.y)); 
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( showMemoryContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( systemMemorySize + " mb" , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Space( size.x);
		GUILayout.Space( size.x);
		GUILayout.Label( "Mem Usage Of Logs " + logsMemUsage.ToString("0.000")  + " mb", nonStyle , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		//GUILayout.Label( "Mem Usage Of Graph " + graphMemUsage.ToString("0.000")  + " mb", nonStyle , GUILayout.Height(size.y));
		//GUILayout.Space( size.x);
		GUILayout.Label( "GC Memory " + gcTotalMemory.ToString("0.000") + " mb",nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( softwareContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( SystemInfo.operatingSystem , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();



		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( dateContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( System.DateTime.Now.ToString() , nonStyle , GUILayout.Height(size.y));
		GUILayout.Label( " - Application Started At " +  logDate , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( showTimeContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( Time.realtimeSinceStartup.ToString("000") , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( showFpsContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( fpsText , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( userContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( UserData , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( showSceneContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( currentScene , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( showSceneContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( "Unity Version = " +Application.unityVersion , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		/*GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Box( graphContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.Label( "frame " + samples.Count , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();*/

		drawInfo_enableDisableToolBarButtons();

		GUILayout.FlexibleSpace();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Label( "Size = "  + size.x.ToString("0.0") , nonStyle , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		float _size = GUILayout.HorizontalSlider( size.x , 16 , 64 ,sliderBackStyle,sliderThumbStyle, GUILayout.Width( Screen.width * 0.5f) ) ;
		if( size.x != _size )
		{
			size.x = size.y = _size;
			initializeStyle();
		}
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		if( GUILayout.Button( backContent ,barStyle ,  GUILayout.Width(size.x*2) , GUILayout.Height(size.y*2)))
		{
			currentView = ReportView.Logs ;
		}
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();



		GUILayout.EndScrollView();

		GUILayout.EndArea();
	}


	void drawInfo_enableDisableToolBarButtons()
	{
		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);
		GUILayout.Label( "Hide or Show tool bar buttons" , nonStyle , GUILayout.Height(size.y));
		GUILayout.Space( size.x);
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Space( size.x);

		if( GUILayout.Button( clearOnNewSceneContent , (showClearOnNewSceneLoadedButton)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) , GUILayout.Height(size.y*2)))
		{
			showClearOnNewSceneLoadedButton = !showClearOnNewSceneLoadedButton;
		}
		
		if( GUILayout.Button( showTimeContent , (showTimeButton)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
		{
			showTimeButton = !showTimeButton ;
		}
		tempRect = GUILayoutUtility.GetLastRect();
		GUI.Label( tempRect , Time.realtimeSinceStartup.ToString("0.0") , lowerLeftFontStyle );
		if( GUILayout.Button( showSceneContent , (showSceneButton)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
		{
			showSceneButton = !showSceneButton ;
		}
		tempRect = GUILayoutUtility.GetLastRect();
		GUI.Label( tempRect , currentScene , lowerLeftFontStyle );
		if( GUILayout.Button( showMemoryContent , (showMemButton)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
		{
			showMemButton = !showMemButton ;
		}
		tempRect = GUILayoutUtility.GetLastRect();
		GUI.Label( tempRect , gcTotalMemory.ToString("0.0") , lowerLeftFontStyle );
		
		if( GUILayout.Button( showFpsContent , (showFpsButton)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
		{
			showFpsButton = !showFpsButton ;
		}
		tempRect = GUILayoutUtility.GetLastRect();
		GUI.Label( tempRect , fpsText , lowerLeftFontStyle );
		/*if( GUILayout.Button( graphContent , (showGraph)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
		{
			showGraph = !showGraph ;
		}
		tempRect = GUILayoutUtility.GetLastRect();
		GUI.Label( tempRect , samples.Count.ToString() , lowerLeftFontStyle );*/
		if( GUILayout.Button( searchContent , (showSearchText)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
		{
			showSearchText = !showSearchText ;
		}
		tempRect = GUILayoutUtility.GetLastRect();
		GUI.TextField( tempRect, filterText ,searchStyle);

		
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();
	}
	void DrawReport()
	{
		screenRect.x = 0f ;
		screenRect.y = 0f ;
		screenRect.width = Screen.width ;
		screenRect.height = Screen.height  ;
		GUILayout.BeginArea( screenRect , backStyle );
		GUILayout.BeginVertical();
		GUILayout.FlexibleSpace();

		GUILayout.BeginHorizontal();
		GUILayout.FlexibleSpace();
		GUILayout.Box( cameraContent ,nonStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.Label( "Select Photo" , nonStyle , GUILayout.Height(size.y));
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.Label( "Comming Soon", nonStyle , GUILayout.Height(size.y));
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		GUILayout.FlexibleSpace();
		if( GUILayout.Button( backContent ,barStyle ,  GUILayout.Width(size.x) , GUILayout.Height(size.y)))
		{
			currentView = ReportView.Logs ;
		}
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();

		GUILayout.FlexibleSpace();
		GUILayout.EndVertical();
		GUILayout.EndArea();
	}

	void drawToolBar(){

		toolBarRect.x = 0f ;
		toolBarRect.y = 0f ;
		toolBarRect.width = Screen.width ;
		toolBarRect.height = size.y * 2f ;

		//toolbarScrollerSkin.verticalScrollbar.fixedWidth = 0f;
		//toolbarScrollerSkin.horizontalScrollbar.fixedHeight= 0f  ;

		GUI.skin = toolbarScrollerSkin ;
		Vector2 drag = getDrag(); 
		if( (drag.x != 0) && (downPos != Vector2.zero) && (downPos.y > Screen.height - size.y * 2f) )
		{
			toolbarScrollPosition.x -= (drag.x - toolbarOldDrag) ;
		}
		toolbarOldDrag = drag.x ;
		GUILayout.BeginArea( toolBarRect );
		toolbarScrollPosition = GUILayout.BeginScrollView( toolbarScrollPosition   );
		GUILayout.BeginHorizontal(  barStyle );
		
		if( GUILayout.Button( clearContent,barStyle ,  GUILayout.Width(size.x*2) , GUILayout.Height(size.y*2)))
		{
			clear();
		}
		if( GUILayout.Button( collapseContent , (collapse)?buttonActiveStyle:barStyle, GUILayout.Width(size.x*2) , GUILayout.Height(size.y*2)))
		{
			collapse = !collapse ;
			calculateCurrentLog();
		}
		if( showClearOnNewSceneLoadedButton && GUILayout.Button( clearOnNewSceneContent , (clearOnNewSceneLoaded)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) , GUILayout.Height(size.y*2)))
		{
			clearOnNewSceneLoaded = !clearOnNewSceneLoaded ;
		}
		
		if( showTimeButton && GUILayout.Button( showTimeContent , (showTime)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
		{
			showTime = !showTime ;
		}
		if( showSceneButton )
		{
			tempRect = GUILayoutUtility.GetLastRect();
			GUI.Label( tempRect , Time.realtimeSinceStartup.ToString("0.0") , lowerLeftFontStyle );
			if( GUILayout.Button( showSceneContent , (showScene)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
			{
				showScene = !showScene ;
			}
			tempRect = GUILayoutUtility.GetLastRect();
			GUI.Label( tempRect , currentScene , lowerLeftFontStyle );
		}
		if( showMemButton )
		{
			if( GUILayout.Button( showMemoryContent , (showMemory)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
			{
				showMemory = !showMemory ;
			}
			tempRect = GUILayoutUtility.GetLastRect();
			GUI.Label( tempRect , gcTotalMemory.ToString("0.0") , lowerLeftFontStyle );
		}
		if( showFpsButton )
		{
			if( GUILayout.Button( showFpsContent , (showFps)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
			{
				showFps = !showFps ;
			}
			tempRect = GUILayoutUtility.GetLastRect();
			GUI.Label( tempRect , fpsText , lowerLeftFontStyle );
		}
		/*if( GUILayout.Button( graphContent , (showGraph)?buttonActiveStyle:barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
		{
			showGraph = !showGraph ;
		}
		tempRect = GUILayoutUtility.GetLastRect();
		GUI.Label( tempRect , samples.Count.ToString() , lowerLeftFontStyle );*/

		if( showSearchText )
		{
			GUILayout.Box( searchContent,barStyle, GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)); 
			tempRect = GUILayoutUtility.GetLastRect();
			string newFilterText = GUI.TextField( tempRect, filterText ,searchStyle);
			if( newFilterText != filterText )
			{
				filterText = newFilterText;
				calculateCurrentLog();
			}
		}

		if( GUILayout.Button( infoContent , barStyle , GUILayout.Width(size.x*2) ,GUILayout.Height(size.y*2)))
		{
			currentView = ReportView.Info ;
		}


		
		GUILayout.FlexibleSpace();
		
		
		string logsText = " " ;
		if( collapse ){
			logsText+= numOfCollapsedLogs ;
		}
		else {
			logsText+= numOfLogs ;
		}
		string logsWarningText = " " ;
		if( collapse ){
			logsWarningText+= numOfCollapsedLogsWarning ;
		}
		else {
			logsWarningText+= numOfLogsWarning ;
		}
		string logsErrorText = " " ;
		if( collapse ){
			logsErrorText+= numOfCollapsedLogsError ;
		}
		else {
			logsErrorText+= numOfLogsError ;
		}
		
		GUILayout.BeginHorizontal( (showLog)?buttonActiveStyle:barStyle );
		if(GUILayout.Button(logContent,nonStyle , GUILayout.Width(size.x*2),GUILayout.Height(size.y*2) ))
		{
			showLog = !showLog ;
			calculateCurrentLog();
		}
		if( GUILayout.Button( logsText ,nonStyle, GUILayout.Width(size.x*2) , GUILayout.Height(size.y*2)))
		{
			showLog = !showLog ;
			calculateCurrentLog();
		}
		GUILayout.EndHorizontal();
		GUILayout.BeginHorizontal( (showWarning)?buttonActiveStyle:barStyle );
		if(GUILayout.Button(warningContent ,nonStyle, GUILayout.Width(size.x*2),GUILayout.Height(size.y*2) ))
		{
			showWarning = !showWarning ;
			calculateCurrentLog();
		}
		if( GUILayout.Button( logsWarningText,nonStyle, GUILayout.Width(size.x*2), GUILayout.Height(size.y*2)))
		{
			showWarning = !showWarning ;
			calculateCurrentLog();
		}
		GUILayout.EndHorizontal();
		GUILayout.BeginHorizontal( (showError)?buttonActiveStyle:nonStyle );
		if(GUILayout.Button(errorContent ,nonStyle, GUILayout.Width(size.x*2),GUILayout.Height(size.y*2) ))
		{
			showError = !showError ;
			calculateCurrentLog();
		}
		if( GUILayout.Button( logsErrorText ,nonStyle, GUILayout.Width(size.x*2), GUILayout.Height(size.y*2)))
		{
			showError = !showError ;
			calculateCurrentLog();
		}
		GUILayout.EndHorizontal();
		
		if( GUILayout.Button(closeContent ,barStyle, GUILayout.Width(size.x*2) , GUILayout.Height(size.y*2)))
		{
			show = false;
            //SSJJ.Manager.EventManager.Instance.RaiseEvent("CloseDebug", null);
			ReporterGUI gui = gameObject.GetComponent<ReporterGUI>();
			DestroyImmediate( gui );

			try{
				gameObject.SendMessage( "OnHideReporter" );
			}
			catch( System.Exception e ){
				Debug.LogException( e );
			}
		}
		
		
		GUILayout.EndHorizontal();
		
		GUILayout.EndScrollView();

		GUILayout.EndArea();
	}

	Rect tempRect ;
	void DrawLogs()
	{

		GUILayout.BeginArea( logsRect , backStyle );

		GUI.skin = logScrollerSkin ;
		//setStartPos();
		Vector2 drag = getDrag(); 
		
		if( drag.y != 0 && logsRect.Contains( new Vector2(downPos.x , Screen.height- downPos.y) ) )
		{
			scrollPosition.y += (drag.y - oldDrag) ;
		}
		scrollPosition = GUILayout.BeginScrollView( scrollPosition   );
		
		oldDrag = drag.y ;
		
		
		int totalVisibleCount = (int)(Screen.height * 0.75f / size.y) ;
		int totalCount = currentLog.Count ;
		/*if( totalCount < 100 )
			inGameLogsScrollerSkin.verticalScrollbarThumb.fixedHeight = 0;
		else 
			inGameLogsScrollerSkin.verticalScrollbarThumb.fixedHeight = 64;*/
		
		totalVisibleCount = Mathf.Min( totalVisibleCount , totalCount - startIndex );
		int index = 0 ;
		int beforeHeight = (int)(startIndex*size.y) ;
		//selectedIndex = Mathf.Clamp( selectedIndex , -1 , totalCount -1);
		if( beforeHeight > 0 )
		{
			//fill invisible gap befor scroller to make proper scroller pos
			GUILayout.BeginHorizontal(  GUILayout.Height( beforeHeight ) );
			GUILayout.Label("---");
			GUILayout.EndHorizontal();
		}
		
		int endIndex = startIndex + totalVisibleCount ;
		endIndex = Mathf.Clamp( endIndex , 0 ,totalCount );
		bool scrollerVisible = (totalVisibleCount < totalCount) ;
		for( int i = startIndex ; (startIndex + index) < endIndex ; i++ )
		{
			
			if( i >= currentLog.Count )
				break;
			Log log = currentLog[i]; 
			
			if( log.logType == _LogType.Log && !showLog )
				continue;
			if( log.logType == _LogType.Warning && !showWarning )
				continue;
			if( log.logType == _LogType.Error && !showError )
				continue;
			if( log.logType == _LogType.Assert && !showError )
				continue;
			if( log.logType == _LogType.Exception && !showError )
				continue;
			
			if( index >= totalVisibleCount )
			{
				break;
			}
			
			GUIContent content = null;
			if( log.logType == _LogType.Log )
				content = logContent ;
			else if( log.logType == _LogType.Warning )
				content = warningContent ;
			else 
				content = errorContent ;
			//content.text = log.condition ;

			GUIStyle currentLogStyle = ((startIndex +index)%2 == 0 )? evenLogStyle : oddLogStyle ;
			if( log == selectedLog ){
				//selectedLog = log ;
				currentLogStyle = selectedLogStyle ;
			}
			else {
			}

			tempContent.text = log.count.ToString();
			float w = 0f ;
			if( collapse )
			 	w = barStyle.CalcSize( tempContent).x + 3 ;
			countRect.x = Screen.width -  w ;
			countRect.y = size.y * i ;
			if( beforeHeight > 0 )
				countRect.y += 8 ;//i will check later why
			countRect.width 	=  w ;
			countRect.height = size.y ;
			
			if( scrollerVisible )
				countRect.x -= size.x *2;

			Sample sample = samples[ log.sampleId ];
			fpsRect = countRect ;
			if( showFps ){
				tempContent.text = sample.fpsText;
				w = currentLogStyle.CalcSize( tempContent ).x + size.x;
				fpsRect.x -= w ;
				fpsRect.width = size.x ;
				fpsLabelRect = fpsRect ;
				fpsLabelRect.x+= size.x ;
				fpsLabelRect.width = w - size.x ;
			}


			memoryRect = fpsRect ;
			if( showMemory ){
				tempContent.text = sample.memory.ToString("0.000");
				w = currentLogStyle.CalcSize( tempContent ).x + size.x;
				memoryRect.x -= w ;
				memoryRect.width = size.x ;
				memoryLabelRect = memoryRect ;
				memoryLabelRect.x+= size.x ;
				memoryLabelRect.width = w - size.x ;
			}
			sceneRect = memoryRect ;
			if( showScene ){
				tempContent.text = scenes[ sample.loadedScene];
				w = currentLogStyle.CalcSize( tempContent ).x + size.x;
				sceneRect.x -= w ;
				sceneRect.width = size.x ;
				sceneLabelRect = sceneRect ;
				sceneLabelRect.x+= size.x ;
				sceneLabelRect.width = w - size.x ;
			}
			timeRect = sceneRect ;
			if( showTime ){
				tempContent.text = sample.time.ToString("0.000");
				w = currentLogStyle.CalcSize( tempContent ).x + size.x;
				timeRect.x -= w ;
				timeRect.width = size.x ;
				timeLabelRect = timeRect ;
				timeLabelRect.x+= size.x ;
				timeLabelRect.width = w - size.x ;
			}



			GUILayout.BeginHorizontal(  currentLogStyle  );
			if( log == selectedLog ){
				GUILayout.Box(content ,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
				GUILayout.Label( log.condition ,selectedLogFontStyle   );
				//GUILayout.FlexibleSpace();
				if( showTime ){
					GUI.Box(timeRect, showTimeContent ,currentLogStyle);
					GUI.Label(timeLabelRect, sample.time.ToString("0.000") ,currentLogStyle   );
				}
				if( showScene ){
					GUI.Box( sceneRect,showSceneContent ,currentLogStyle);
					GUI.Label( sceneLabelRect ,scenes[ sample.loadedScene] ,currentLogStyle   );
				}
				if( showMemory ){
					GUI.Box(memoryRect, showMemoryContent ,currentLogStyle );
					GUI.Label( memoryLabelRect ,sample.memory.ToString("0.000") + " mb" ,currentLogStyle   );
				}
				if( showFps ){
					GUI.Box(fpsRect, showFpsContent ,currentLogStyle);
					GUI.Label( fpsLabelRect , sample.fpsText ,currentLogStyle   );
				}
				

			}
			else {
				if(GUILayout.Button(content ,nonStyle, GUILayout.Width(size.x),GUILayout.Height(size.y) ))
				{
					//selectedIndex = startIndex + index ;
					selectedLog = log;
				}
				if( GUILayout.Button( log.condition ,logButtonStyle ) )
				{
					//selectedIndex = startIndex + index ;
					selectedLog = log;
				}
				//GUILayout.FlexibleSpace();
				if( showTime ){
					GUI.Box(timeRect, showTimeContent ,currentLogStyle) ;
					GUI.Label(timeLabelRect, sample.time.ToString("0.000") ,currentLogStyle )  ;
				}
				if( showScene ){
					GUI.Box(sceneRect, showSceneContent ,currentLogStyle) ;
					GUI.Label( sceneLabelRect, scenes[ sample.loadedScene] ,currentLogStyle  ) ;
				}
				if( showMemory ){
					GUI.Box( memoryRect, showMemoryContent ,currentLogStyle) ;
					GUI.Label( memoryLabelRect, sample.memory.ToString("0.000") + " mb" ,currentLogStyle  ) ;
				}
				if( showFps ){
					GUI.Box(fpsRect,showFpsContent ,currentLogStyle );
					GUI.Label( fpsLabelRect ,sample.fpsText ,currentLogStyle  ) ;
				}
			}
			if( collapse )
				GUI.Label( countRect ,log.count.ToString() ,barStyle );
			GUILayout.EndHorizontal();
			index++;
		}
		
		int afterHeight = (int)((totalCount - ( startIndex + totalVisibleCount ))*size.y) ;
		if( afterHeight > 0 )
		{
			//fill invisible gap after scroller to make proper scroller pos
			GUILayout.BeginHorizontal(  GUILayout.Height(afterHeight ) );
			GUILayout.Label(" ");
			GUILayout.EndHorizontal();
		}

		GUILayout.EndScrollView();
		GUILayout.EndArea();

		buttomRect.x = 0f ;
		buttomRect.y = Screen.height - size.y ;
		buttomRect.width = Screen.width ;
		buttomRect.height = size.y ;

		if( showGraph )
			drawGraph();
		else 
			drawStack();
	}

	float graphSize = 4f ;
	int startFrame = 0 ;
	int currentFrame = 0 ;
	Vector3 tempVector1 ;
	Vector3 tempVector2 ;
	Vector2 graphScrollerPos ;
	float maxFpsValue  ;
	float minFpsValue ;
	float maxMemoryValue ;
	float minMemoryValue  ;
	void drawGraph(){

		graphRect = stackRect ;
		graphRect.height = Screen.height * 0.25f ;//- size.y ;



		//startFrame = samples.Count - (int)(Screen.width / graphSize) ;
		//if( startFrame < 0 ) startFrame = 0 ;
		GUI.skin = graphScrollerSkin ;

		Vector2 drag = getDrag(); 
		if(  graphRect.Contains( new Vector2(downPos.x , Screen.height- downPos.y) ) ){
			if( drag.x != 0 ){
				graphScrollerPos.x -= drag.x - oldDrag3 ;
				graphScrollerPos.x = Mathf.Max( 0 , graphScrollerPos.x );
			}

			Vector2 p = downPos ;
			if( p != Vector2.zero ){
				currentFrame = startFrame + (int)(p.x  /  graphSize);
			}
		}

		oldDrag3 = drag.x ;
		GUILayout.BeginArea( graphRect , backStyle );

		graphScrollerPos = GUILayout.BeginScrollView( graphScrollerPos  );
		startFrame = (int)(graphScrollerPos.x / graphSize) ;
		if( graphScrollerPos.x >= (samples.Count * graphSize - Screen.width) )
			graphScrollerPos.x += graphSize ;

		GUILayout.Label(" " , GUILayout.Width( samples.Count * graphSize ));
		GUILayout.EndScrollView();
		GUILayout.EndArea();
		maxFpsValue = 0 ;
		minFpsValue = 100000 ;
		maxMemoryValue = 0 ;
		minMemoryValue = 100000 ;
		for( int i = 0 ; i < Screen.width/ graphSize ; i++ ){
			int index = startFrame + i ;
			if( index >= samples.Count )
				break;
			Sample s = samples[index];
			if( maxFpsValue < s.fps ) maxFpsValue = s.fps ;
			if( minFpsValue > s.fps ) minFpsValue = s.fps ;
			if( maxMemoryValue < s.memory ) maxMemoryValue = s.memory ;
			if( minMemoryValue > s.memory ) minMemoryValue = s.memory ;
		}

		//GUI.BeginGroup(graphRect);


		if( currentFrame != -1 && currentFrame < samples.Count ){
			Sample selectedSample = samples[ currentFrame ] ;
			GUILayout.BeginArea( buttomRect , backStyle);
			GUILayout.BeginHorizontal( ); 
			
			GUILayout.Box( showTimeContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
			GUILayout.Label( selectedSample.time.ToString("0.0"),nonStyle );
			GUILayout.Space( size.x );

			GUILayout.Box( showSceneContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
			GUILayout.Label( scenes[ selectedSample.loadedScene],nonStyle );
			GUILayout.Space( size.x );
			
			GUILayout.Box( showMemoryContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
			GUILayout.Label( selectedSample.memory.ToString("0.000") ,nonStyle);
			GUILayout.Space( size.x );
			
			GUILayout.Box( showFpsContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
			GUILayout.Label( selectedSample.fpsText ,nonStyle);
			GUILayout.Space( size.x );

			GUILayout.Box( graphContent ,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
			GUILayout.Label( currentFrame.ToString() ,nonStyle  );
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.EndArea();
		}

		graphMaxRect = stackRect ;
		graphMaxRect.height = size.y ;
		GUILayout.BeginArea( graphMaxRect );
		GUILayout.BeginHorizontal( ); 
		
		GUILayout.Box( showMemoryContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
		GUILayout.Label( maxMemoryValue.ToString("0.000") ,nonStyle);
		
		GUILayout.Box( showFpsContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
		GUILayout.Label( maxFpsValue.ToString("0.000") ,nonStyle);
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();
		GUILayout.EndArea();

		graphMinRect = stackRect ;
		graphMinRect.y = stackRect.y + stackRect.height - size.y ;
		graphMinRect.height = size.y ;
		GUILayout.BeginArea( graphMinRect );
		GUILayout.BeginHorizontal( ); 
		
		GUILayout.Box( showMemoryContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));

		GUILayout.Label( minMemoryValue.ToString("0.000") ,nonStyle);

		
		GUILayout.Box( showFpsContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));

		GUILayout.Label( minFpsValue.ToString("0.000") ,nonStyle);
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();
		GUILayout.EndArea();

		//GUI.EndGroup();
	}
	void drawStack(){

		if( selectedLog != null)
		{
			Vector2 drag = getDrag(); 
			if( drag.y != 0 && stackRect.Contains( new Vector2(downPos.x , Screen.height- downPos.y) ) )
			{
				scrollPosition2.y += drag.y - oldDrag2 ;
			}
			oldDrag2 = drag.y ;

			

			GUILayout.BeginArea( stackRect , backStyle );
			scrollPosition2 = GUILayout.BeginScrollView( scrollPosition2  );
			Sample selectedSample=null;
			try{
				selectedSample = samples[ selectedLog.sampleId ] ;
			}
			catch( System.Exception e ){
				Debug.LogException( e );
			}

			GUILayout.BeginHorizontal( ); 
			GUILayout.Label(  selectedLog.condition , stackLabelStyle );
			GUILayout.EndHorizontal();
			GUILayout.Space( size.y*0.25f );
			GUILayout.BeginHorizontal();
			GUILayout.Label(   selectedLog.stacktrace , stackLabelStyle );
			GUILayout.EndHorizontal();
			GUILayout.Space( size.y );
			GUILayout.EndScrollView();
			GUILayout.EndArea();


			GUILayout.BeginArea( buttomRect , backStyle);
			GUILayout.BeginHorizontal( ); 
			
			GUILayout.Box( showTimeContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
			GUILayout.Label( selectedSample.time.ToString("0.000"),nonStyle );
			GUILayout.Space( size.x );
			
			GUILayout.Box( showSceneContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
			GUILayout.Label( scenes[ selectedSample.loadedScene],nonStyle );
			GUILayout.Space( size.x );
			
			GUILayout.Box( showMemoryContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
			GUILayout.Label( selectedSample.memory.ToString("0.000") ,nonStyle);
			GUILayout.Space( size.x );
			
			GUILayout.Box( showFpsContent,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
			GUILayout.Label( selectedSample.fpsText ,nonStyle);
			/*GUILayout.Space( size.x );
			GUILayout.Box( graphContent ,nonStyle, GUILayout.Width(size.x) ,GUILayout.Height(size.y));
			GUILayout.Label( selectedLog.sampleId.ToString() ,nonStyle  );*/
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.EndArea();

			

		}
		else {
			GUILayout.BeginArea( stackRect , backStyle );
			GUILayout.EndArea();
			GUILayout.BeginArea( buttomRect , backStyle );
			GUILayout.EndArea();
		}

	}


	public void OnGUIDraw()
	{

		if( !show )
		{
			return ;
		}

		screenRect.x = 0 ;
		screenRect.y = 0 ;
		screenRect.width = Screen.width ;
		screenRect.height = Screen.height;

		getDownPos();


		logsRect.x = 0f ;
		logsRect.y = size.y * 2f ;
		logsRect.width = Screen.width ;
		logsRect.height = Screen.height * 0.75f - size.y * 2f ;
		
		stackRectTopLeft.x = 0f ;
		stackRect.x = 0f ;
		stackRectTopLeft.y = Screen.height * 0.75f ;
		stackRect.y = Screen.height * 0.75f ;
		stackRect.width = Screen.width ;
		stackRect.height = Screen.height * 0.25f - size.y ;
		
		
		
		detailRect.x = 0f ;
		detailRect.y = Screen.height  - size.y*3;
		detailRect.width = Screen.width ;
		detailRect.height = size.y * 3;

		if( currentView == ReportView.Info )
			DrawInfo();
		else if( currentView == ReportView.Logs ){
			drawToolBar();
			DrawLogs();
		}


	}
	
	List<Vector2> gestureDetector = new List<Vector2>();
	Vector2 gestureSum = Vector2.zero ;
	float gestureLength = 0;
	int gestureCount = 0;
	bool isGestureDone()
	{
		if( Application.platform == RuntimePlatform.Android || 
			Application.platform == RuntimePlatform.IPhonePlayer )
		{
			if( Input.touches.Length != 1 )
			{
				gestureDetector.Clear();
				gestureCount = 0;
			}
			else 
			{
				if( Input.touches[0].phase == TouchPhase.Canceled || Input.touches[0].phase == TouchPhase.Ended )
					gestureDetector.Clear();
				else if( Input.touches[0].phase == TouchPhase.Moved )
				{
					Vector2 p = Input.touches[0].position;
					if( gestureDetector.Count == 0 ||  (p - gestureDetector[ gestureDetector.Count-1]).magnitude > 10 )
						gestureDetector.Add( p ) ;
				}
			}
		}
		else 
		{
			if( Input.GetMouseButtonUp(0) )
			{
				gestureDetector.Clear();
				gestureCount = 0;
			}
			else 
			{
				if( Input.GetMouseButton(0))
				{
					Vector2 p = new Vector2( Input.mousePosition.x , Input.mousePosition.y );
					if( gestureDetector.Count == 0 ||  (p - gestureDetector[ gestureDetector.Count-1]).magnitude > 10 )
						gestureDetector.Add( p );
				}
			}
		}
		
		if( gestureDetector.Count < 10 )
			return false;
		
		gestureSum = Vector2.zero ;
		gestureLength  = 0 ;
		Vector2 prevDelta = Vector2.zero ;
		for( int i = 0 ; i < gestureDetector.Count - 2 ; i++ )
		{
			
			Vector2 delta = gestureDetector[i+1] - gestureDetector[i] ;
			float deltaLength = delta.magnitude ;
			gestureSum += delta  ; 
			gestureLength += deltaLength ; 
			
			float dot =  Vector2.Dot( delta , prevDelta ) ;
			if( dot < 0f )
			{
				gestureDetector.Clear();
				gestureCount = 0;
				return false;
			}
			
			prevDelta = delta ;
		}
		
		int gestureBase = (Screen.width + Screen.height ) / 4 ;
		
		if( gestureLength > gestureBase && gestureSum.magnitude < gestureBase/2 )
		{
			gestureDetector.Clear();
			gestureCount++;
			if( gestureCount >= numOfCircleToShow ) 
				return true ;
		}
		
		return false ;
	}

	float lastClickTime = -1 ;
	bool isDoubleClickDone()
	{
		if( Application.platform == RuntimePlatform.Android || 
		   Application.platform == RuntimePlatform.IPhonePlayer )
		{
			if( Input.touches.Length != 1 )
			{
				lastClickTime = -1 ;
			}
			else 
			{
				if( Input.touches[0].phase == TouchPhase.Began ){
					if( lastClickTime == -1 )
						lastClickTime = Time.realtimeSinceStartup ;
					else if( Time.realtimeSinceStartup - lastClickTime < 0.2f ){
						lastClickTime = -1 ;
						return true ;
					}
					else{
						lastClickTime = Time.realtimeSinceStartup ;
					}
				}
			}
		}
		else 
		{
			if( Input.GetMouseButtonDown(0))
			{
				if( lastClickTime == -1 )
					lastClickTime = Time.realtimeSinceStartup ;
				else if( Time.realtimeSinceStartup - lastClickTime < 0.2f ){
					lastClickTime = -1 ;
					return true ;
				}
				else{
					lastClickTime = Time.realtimeSinceStartup ;
				}
			}
		}
		return false ;
	}

	//calculate  pos of first click on screen
	Vector2 startPos ;

	Vector2 downPos ;
	Vector2 getDownPos()
	{
		if( Application.platform == RuntimePlatform.Android || 
		   Application.platform == RuntimePlatform.IPhonePlayer )
		{
			
			if( Input.touches.Length == 1 &&  Input.touches[0].phase == TouchPhase.Began )
			{
				downPos = Input.touches[0].position ;
				return  downPos ;
			}
		}
		else 
		{
			if( Input.GetMouseButtonDown(0) )
			{
				downPos.x = Input.mousePosition.x ;
				downPos.y = Input.mousePosition.y ;
				return  downPos ;
			}
		}

		return Vector2.zero ;
	}
	//calculate drag amount , this is used for scrolling

	Vector2 mousePosition ;
	Vector2 getDrag()
	{
		
		if( Application.platform == RuntimePlatform.Android || 
			Application.platform == RuntimePlatform.IPhonePlayer )
		{
			if( Input.touches.Length != 1 )
			{
				return Vector2.zero ;
			}
			return Input.touches[0].position - downPos ;
		}
		else 
		{
			if( Input.GetMouseButton(0) )
			{
				mousePosition = Input.mousePosition ;
				return mousePosition - downPos ;
			}
			else 
			{
				return Vector2.zero;
			}
		}
	}

	//calculate the start index of visible log
	void calculateStartIndex()
	{
		startIndex = (int)(scrollPosition.y /size.y)  ;
		startIndex = Mathf.Clamp( startIndex , 0 , currentLog.Count );
	}

	float lastUpdate = 0;
	float lastUpdate2 = 0;
	Rect temp;
	void doShow(){
		show = true; 
		currentView = ReportView.Logs ;
		gameObject.AddComponent<ReporterGUI>();
		

		try{
			gameObject.SendMessage( "OnShowReporter");
		}
		catch(System.Exception e ){
			Debug.LogException( e );
		}
	}
	void Update()
	{
		fpsText = fps.ToString("0.000");
		gcTotalMemory = (((float)System.GC.GetTotalMemory(false))/1024/1024) ;
		//addSample();
		if( string.IsNullOrEmpty( scenes[0] ))
			scenes[0] = Application.loadedLevelName ;

		float elapsed = Time.realtimeSinceStartup - lastUpdate ;
		fps = 1f / elapsed ;
		lastUpdate = Time.realtimeSinceStartup ;
		calculateStartIndex();
		if(!show && isGestureDone()&&(Application.targetFrameRate==46||Application.loadedLevelName!="Battle"))
		{
			doShow();
		}


		if( threadedLogs.Count > 0 )
		{
			lock( threadedLogs )
			{
				for( int i = 0 ; i < threadedLogs.Count ; i++ )
				{
					Log l = threadedLogs[i];
					AddLog( l.condition, l.stacktrace, (LogType)l.logType );
				}
				threadedLogs.Clear();
			}
		}

		float elapsed2 = Time.realtimeSinceStartup - lastUpdate2 ;
		if( elapsed2 > 1)
		{
			lastUpdate2 = Time.realtimeSinceStartup ;
			//be sure no body else take control of log 
#if USE_OLD_UNITY
			Application.RegisterLogCallback (new Application.LogCallback (CaptureLog));
			Application.RegisterLogCallbackThreaded (new Application.LogCallback (CaptureLogThread));
#endif
		}
	}


	void CaptureLog (string condition, string stacktrace, LogType type)
	{
		AddLog(condition, stacktrace, type );
	}

	void AddLog( string condition, string stacktrace, LogType type )
	{
		float memUsage = 0f ;
		string _condition = "";
		if( cachedString.ContainsKey( condition ) )
		{
			_condition = cachedString[ condition ];
		}
		else 
		{
			_condition = condition ;
			cachedString.Add( _condition , _condition );
			memUsage += (string.IsNullOrEmpty(_condition)?0:_condition.Length*sizeof(char));
			memUsage += System.IntPtr.Size ;
		}
		string _stacktrace = "";
		if( cachedString.ContainsKey( stacktrace ) )
		{
			_stacktrace = cachedString[ stacktrace ];
		}
		else 
		{
			_stacktrace = stacktrace ;
			cachedString.Add( _stacktrace , _stacktrace );
			memUsage += (string.IsNullOrEmpty(_stacktrace)?0:_stacktrace.Length*sizeof(char));
			memUsage += System.IntPtr.Size ;
		}
		bool newLogAdded = false ;
		
		addSample();
		Log log = new Log(){ logType = (_LogType)type , condition = _condition  , stacktrace = _stacktrace , sampleId = samples.Count -1  };
		memUsage += log.GetMemoryUsage() ;
		//memUsage += samples.Count * 13 ;
		
		logsMemUsage += memUsage/1024/1024;
		
		if( TotalMemUsage > maxSize )
		{
			clear();
			Debug.Log( "Memory Usage Reach" + maxSize +" mb So It is Cleared");
			return;
		}
		
		bool isNew = false ;
		//string key = _condition;// + "_!_" + _stacktrace ;
		if( logsDic.ContainsKey( _condition ,stacktrace) )
		{
			isNew = false ;
			logsDic[ _condition ][stacktrace].count ++;
		}
		else 
		{
			isNew = true ;
			collapsedLogs.Add( log );
			logsDic[_condition][stacktrace] = log ;
			
			if( type == LogType.Log )
				numOfCollapsedLogs++;
			else if( type == LogType.Warning )
				numOfCollapsedLogsWarning++;
			else 
				numOfCollapsedLogsError++;
		}
		
		if( type == LogType.Log )
			numOfLogs++;
		else if( type == LogType.Warning )
			numOfLogsWarning++;
		else 
			numOfLogsError++;
		
		
		logs.Add( log );
		if( !collapse || isNew )
		{
			bool skip = false ;
			if( log.logType == _LogType.Log && !showLog )
				skip = true;
			if( log.logType == _LogType.Warning && !showWarning )
				skip = true;
			if( log.logType == _LogType.Error && !showError )
				skip = true;
			if( log.logType == _LogType.Assert && !showError )
				skip = true;
			if( log.logType == _LogType.Exception && !showError )
				skip = true;
			
			if( !skip)
			{
				if( string.IsNullOrEmpty(filterText ) || log.condition.ToLower().Contains( filterText.ToLower() ))
				{
					currentLog.Add( log );
					newLogAdded=true;
				}
			}
		}
		
		if( newLogAdded )
		{
			calculateStartIndex();
			int totalCount = currentLog.Count;
			int totalVisibleCount = (int)(Screen.height * 0.75f / size.y) ;
			if( startIndex >= ( totalCount - totalVisibleCount ))
				scrollPosition.y += size.y ;
		}
		
		try
		{
			gameObject.SendMessage( "OnLog" ,log );
		}
		catch( System.Exception e )
		{
			Debug.LogException( e );
		}
	}

	List<Log> threadedLogs = new List<Log>();
	void CaptureLogThread (string condition, string stacktrace, LogType type)
	{
		Log log = new Log(){ condition = condition , stacktrace = stacktrace , logType = (_LogType)type };
		lock( threadedLogs )
		{
			threadedLogs.Add( log );
		}
	}
	
	//new scene is loaded
	void OnLevelWasLoaded()
	{
		if( clearOnNewSceneLoaded )
			clear();

		currentScene = Application.loadedLevelName ;
		Debug.Log( "Scene " + Application.loadedLevelName + " is loaded");
	}
	
	//save user config
	void OnApplicationQuit()
	{
		PlayerPrefs.SetInt( "Reporter_currentView" ,(int)currentView);
		PlayerPrefs.SetInt( "Reporter_show" ,(show==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_collapse" ,(collapse==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_clearOnNewSceneLoaded" ,(clearOnNewSceneLoaded==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showTime" ,(showTime==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showScene" ,(showScene==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showMemory" ,(showMemory==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showFps" ,(showFps==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showGraph" ,(showGraph==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showLog" ,(showLog==true)?1:0) ;
		PlayerPrefs.SetInt( "Reporter_showWarning" ,(showWarning==true)?1:0) ;
		PlayerPrefs.SetInt( "Reporter_showError" ,(showError==true)?1:0) ;
		PlayerPrefs.SetString( "Reporter_filterText" , filterText );
		PlayerPrefs.SetFloat( "Reporter_size" , size.x );

		PlayerPrefs.SetInt( "Reporter_showClearOnNewSceneLoadedButton" ,(showClearOnNewSceneLoadedButton==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showTimeButton" ,(showTimeButton==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showSceneButton" ,(showSceneButton==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showMemButton" ,(showMemButton==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showFpsButton" ,(showFpsButton==true)?1:0);
		PlayerPrefs.SetInt( "Reporter_showSearchText" ,(showSearchText==true)?1:0);

		PlayerPrefs.Save();
	}
	
	//read build information 
	IEnumerator readInfo(  )
	{
		string prefFile = "build_info.txt" ;
		string url = prefFile;

        if (prefFile.IndexOf("://") == -1)
        {
            string streamingAssetsPath = Application.streamingAssetsPath;
            if (streamingAssetsPath == "")
                streamingAssetsPath = Application.dataPath + "/StreamingAssets/";
            url = System.IO.Path.Combine(streamingAssetsPath, prefFile);
        }

        if (Application.platform != RuntimePlatform.OSXWebPlayer && Application.platform != RuntimePlatform.WindowsWebPlayer)
            if (!url.Contains("://"))
                url = "file://" + url;


       // float startTime = Time.realtimeSinceStartup;
		WWW www = new WWW( url );
		yield return www ;
		
		if( !string.IsNullOrEmpty( www.error ) )
		{
			//Debug.LogError( www.error );
		}
		else 
		{
			buildDate = www.text ;
		}
		
		yield break;
	}
}


